﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<stdlib.h>
#include<assert.h>

//在上个程序（类和对象_拷贝构造.cpp)中，不得已已经提前使用了赋值运算符重载，以前也写过名为“运算符重载.cpp”的程序
//对运算符重载进行了相关介绍，但是，赋值运算符重载较为特殊，有着更严格的规则：
//1.它必须要写为成员函数，
//2.当不主动进行书写时，编译器会自动生成一个可用于浅拷贝的赋值运算符重载
//3.当赋值运算符重载遇到类类型成员​​时，调用该成员自身的拷贝赋值运算符
// 
//能够发现，以上三点和拷贝构造函数完全一致，且两者的作用也都是拷贝，但需要注意，拷贝构造的作用是初始化对象；
//而赋值运算符重载的作用确实讲已经初始化完毕的变量赋值给另一个已经初始化完毕的变量（正因此，在复制前要先free原来的空间，保证赋值后开辟的空间数量一致）
//同时，也有两点不同：
//1.赋值重载要有返回值，作用是为了支持赋值运算符的连续赋值操作（返回值一般为this指针的解引用）
//2.建议将赋值重载的参数写成const类型的引用，返回值写为T&类型（避免传值传参自动调用拷贝构造，降低程序效率）
//注：返回值不建议为const类型的原因是为了与C语言赋值运算符的返回值类型保持一致
//	  拷贝构造的要求是参数必须写成const T&或T&（若传值调用则会陷入死循环）


//默认赋值运算符重载浅拷贝示例：
//class Data
//{
//public:
//	//默认构造函数
//	Data(int year = 2025, int month = 7, int day = 10)
//	{
//		_year = year;
//		_month = month;
//		_day = day;
//	}
//	//由于成员都是内置类型，且无需开辟空间，所以直接使用默认赋值重载即可
//
//	void Print()
//	{
//		std::cout << "_year:" << _year << " _month:" << _month << " _day:" << _day << std::endl;
//	}
//private:
//	int _year;
//	int _month;
//	int _day;
//};
//class dzh1
//{
//public:
//	//默认构造函数：
//	dzh1(int x = 1, int y = 1, int z = 1)
//	{
//		_x = x;
//		_y = y;
//		_z = z;
//	}
//	//由于没有需要申请空间的变量，所以直接是应用默认赋值重载即可
//
//	void Print()
//	{
//		_a.Print();
//		std::cout << "_x:" << _x << " _y:" << _y << " _z:" << _z << " _p:" << _p << std::endl;
//	}
//private:
//	int _x;
//	int _y;
//	int _z;
//	Data _a;
//	int* _p = &_z;
//};
//
//int main()
//{
//	dzh1 a(1, 2, 3);
//	a.Print();//_year:2025 _month:7 _day:10\n_x:1 _y:2 _z:3 _p:000000DBC00FF9D0
//	dzh1 b(996, 996, 996);
//	b.Print();//_year:2025 _month:7 _day:10\n_x:996 _y:996 _z:996 _p:000000DBC00FFA10
//	//使用默认赋值重载：
//	a = b;
//	a.Print();//_year:2025 _month:7 _day:10\n_x:996 _y:996 _z:996 _p:000000DBC00FFA10
//	//由打印结果可以看出，默认赋值重载已经完成了拷贝，且是浅拷贝
//	return 0;
//}



//赋值运算符重载深拷贝情况示例：
class Data
{
public:
	//默认构造函数
	Data(int year = 2025, int month = 7, int day = 10)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//由于成员都是内置类型，且无需开辟空间，所以直接使用默认赋值重载即可，也不需要析构函数

	void Print()
	{
		std::cout << "_year:" << _year << " _month:" << _month << " _day:" << _day << std::endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
class dzh1
{
public:
	//默认构造函数：
	dzh1(int x = 1, int y = 1, int z = 1)
	{
		_x = x;
		_y = y;
		_z = z;
		_p = (int*)malloc(sizeof(int) * (_x + _y + _z));
		assert(_p);
		for (int i = 0; i < _x + _y + _z && i < 10; i++)
		{
			_p[i] = i;
		}
	}
	//析构函数
	~dzh1()
	{
		free(_p);
		_p = nullptr;
	}
	//赋值重载
	dzh1& operator=(const dzh1& a)
	{
		_x = a._x;
		_y = a._y;
		_z = a._z;
		//释放原来的空间（不要忘记释放原来的空间）
		free(_p);
		_p = nullptr;
		_p = (int*)malloc(sizeof(int) * (_x + _y + _z));
		assert(_p);
		for (int i = 0; i < _x + _y + _z && i < 10; i++)
		{
			_p[i] = a._p[i];
		}
		return *this;//一般返回this指针的解引用
	}
	void Print()
	{
		_a.Print();
		std::cout << "_x:" << _x << " _y:" << _y << " _z:" << _z  << " p:" << _p << std::endl;
		for (int i = 0; i < _x + _y + _z && i < 10; i++)
		{
			std::cout << _p[i] << " " << std::endl;
		}
	}
private:
	int _x;
	int _y;
	int _z;
	Data _a;
	int* _p = nullptr;
};

int main()
{
	dzh1 a(1, 2, 3);
	a.Print();
	dzh1 b(996, 996, 996);
	b.Print();
	a = b;
	a.Print();//运行后可知，深拷贝成功
	dzh1 c;
	c = a = b;//验证赋值运算符连等
	c.Print();
	return 0;
}
